﻿using MvCamCtrl.NET;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net.NetworkInformation;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MvCamCtrl.NET.CameraParams;
using System.Security.Policy;
using System.Drawing.Imaging;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;

namespace LKL_Code.Camera
{
    public class Camera_HkVision : ICamera
    {
        //实例化相机m_MyCamera
        private CCamera m_MyCamera = new CCamera();

        //相机设备列表
        List<CCameraInfo> m_ltDeviceList = new List<CCameraInfo>();

        /// <summary>
        /// 控件操作
        /// </summary>
        public Control_Operation Control_Operation
        {
            get
            {
                return control_Operation;
            }
        }

        private Control_Operation control_Operation;
        public bool m_bGrabbing { get; set; }//采集开关

        public bool m_bRecord { get; set; } //记录开关

        Thread m_hReceiveThread = null;   //接受的线程

        public List<string> ComboxItems { get; set; }



        public void AddComboxItem(string ComboxItem) // 添加一个字符串到数组中。
        {

            ComboxItems.Add(ComboxItem);
        }

        public string GetComboxItem(int index)//获取指定索引处的字符串
        {
            if (index < 0 || index >= ComboxItems.Count)
                throw new ArgumentOutOfRangeException(nameof(index));
            return ComboxItems[index];
        }

        public string[] GetAllComboxItem()//返回整个字符串数组。
        {
            return ComboxItems.ToArray();
        }

        public int Count => ComboxItems.Count;//获取数组中字符串的数量



        //用于驱动获取图像的缓存
        private static Object BufForDriverLock = new Object();

        CImage m_pcImgForDriver = null;        // 图像信息
        CFrameSpecInfo m_pcImgSpecInfo = null; // 图像的水印信息
        CSaveImageParam m_pcSaveParam = new CSaveImageParam(); //保存到缓存的参数信息

        // ch:Bitmap | en:Bitmap
        public bool m_bRenderByBitmap { get; set; }//渲染位图

        public Graphics m_pcGraphic1 = null; //图形1
        public Graphics m_pcGraphic2 = null;//图形2

        //宽
        public UInt32 m_nCurWidth { get; set; }
        // 高
        public UInt32 m_nCurHeight { get; set; }

        MvGvspPixelType m_emPixelType = MvGvspPixelType.PixelType_Gvsp_Mono8;  //像素格式



        public Graphics Picture1_CreateGraphics { get; set; }

        public Graphics Picture2_CreateGraphics { get; set; }

        public int PictureBox1_W { get; set; }

        public int PictureBox1_H { get; set; }
        public int PictureBox2_W { get; set; }

        public int PictureBox2_H { get; set; }
        public IntPtr Picture1_Handle { get; set; }
        public IntPtr Picture2_Handle { get; set; }
        public bool bnTriggerMode_Checked { get; set; }

        /// <summary>
        /// 曝光
        /// </summary>
        public string tbExposure_Text { get; set; }

        /// <summary>
        /// 增益
        /// </summary>
        public string tbGain_Text { get; set; }

        /// <summary>
        /// 帧率
        /// </summary>
        public string tbFrameRate_Text { get; set; }

        /// <summary>
        /// 像素格式
        /// </summary>
        public string tbPixelFormat_Text { get; set; }

        public bool[] controls = new bool[] { };//控件使能or点击 值传递
        /// <summary>
        /// 初始化
        /// </summary>
        public void Initialize()
        {

            m_bGrabbing = false;

            m_bRecord = false;

            m_bRenderByBitmap = false;

            m_pcGraphic1 = null;  //图形

            m_nCurWidth = 0; //宽

            m_nCurHeight = 0;//高

        }





        //显示错误信息
        public void ShowErrorMsg(string csMessage, int nErrorNum)
        {
            string errorMsg;
            if (nErrorNum == 0)
            {
                errorMsg = csMessage;
            }
            else
            {
                errorMsg = csMessage + ": Error =" + String.Format("{0:X}", nErrorNum);
            }

            switch (nErrorNum)
            {
                case CErrorDefine.MV_E_HANDLE: errorMsg += " Error or invalid handle "; break;
                case CErrorDefine.MV_E_SUPPORT: errorMsg += " Not supported function "; break;
                case CErrorDefine.MV_E_BUFOVER: errorMsg += " Cache is full "; break;
                case CErrorDefine.MV_E_CALLORDER: errorMsg += " Function calling order error "; break;
                case CErrorDefine.MV_E_PARAMETER: errorMsg += " Incorrect parameter "; break;
                case CErrorDefine.MV_E_RESOURCE: errorMsg += " Applying resource failed "; break;
                case CErrorDefine.MV_E_NODATA: errorMsg += " No data "; break;
                case CErrorDefine.MV_E_PRECONDITION: errorMsg += " Precondition error, or running environment changed "; break;
                case CErrorDefine.MV_E_VERSION: errorMsg += " Version mismatches "; break;
                case CErrorDefine.MV_E_NOENOUGH_BUF: errorMsg += " Insufficient memory "; break;
                case CErrorDefine.MV_E_UNKNOW: errorMsg += " Unknown error "; break;
                case CErrorDefine.MV_E_GC_GENERIC: errorMsg += " General error "; break;
                case CErrorDefine.MV_E_GC_ACCESS: errorMsg += " Node accessing condition error "; break;
                case CErrorDefine.MV_E_ACCESS_DENIED: errorMsg += " No permission "; break;
                case CErrorDefine.MV_E_BUSY: errorMsg += " Device is busy, or network disconnected "; break;
                case CErrorDefine.MV_E_NETER: errorMsg += " Network error "; break;
            }

            MessageBox.Show(errorMsg, "PROMPT");
        }
        public void DebugInfo(string strInfo)
        {
            string strRes = "BasicDemo";
            System.Diagnostics.Debug.WriteLine(strRes + strInfo);     //将 strRes 和 strInfo 两个字符串连接起来，并将结果写入调试输出窗口。这在调试过程中可以帮助你查看这些变量的值。
        }

        public Boolean IsMonoData(MvGvspPixelType enGvspPixelType)   //Boolean 类型表示为 bool，它是 System.Boolean 的别名。
        {
            switch (enGvspPixelType)  //像素类型
            {
                case MvGvspPixelType.PixelType_Gvsp_Mono8:
                case MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                    return true;

                default:
                    return false;
            }
        }



        /************************************************************************
         *  @fn     IsColorData()
         *  @brief  判断是否是彩色数据
         *  @param  enGvspPixelType         [IN]           像素格式
         *  @return 成功，返回0；错误，返回-1 
         ************************************************************************/
        public Boolean IsColorData(MvGvspPixelType enGvspPixelType)
        {
            switch (enGvspPixelType)
            {
                case MvGvspPixelType.PixelType_Gvsp_BayerGR8:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG8:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB8:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG8:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR10:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG10:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB10:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG10:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR12:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG12:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB12:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG12:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
                case MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
                case MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
                    return true;
                default:
                    return false;
            }
        }

        //查找设备
        public void DeviceListAcq()//, List<string> ComboxItems
        {
            ComboxItems = new List<string>();
            //传递字符串ComboxList
            //ComboxItems = new List<string>();
            // ch:创建设备列表 | en:Create Device List
            System.GC.Collect();  //立即启动垃圾回收过程，尝试回收所有代（generation）中的内存。垃圾回收器会检查哪些对象不再使用，并释放这些对象占用的内存。                                
            ComboxItems.Clear(); //cbDeviceList.Items.Clear();  //CBox选项清空
            m_ltDeviceList.Clear();  //清空相机设备列表

            int nRet = CSystem.EnumDevices(CSystem.MV_GIGE_DEVICE | CSystem.MV_USB_DEVICE, ref m_ltDeviceList);
            //这行代码的作用是调用 CSystem 类的静态方法 EnumDevices，以枚举GIGE和USB两种类型的设备，
            //并将枚举到的设备信息存储在 m_ltDeviceList 中。
            //返回值 nRet 通常表示操作的结果状态。

            if (0 != nRet)  //没找到相机
            {
                ShowErrorMsg("Enumerate devices fail!", 0);
                return;
            }

            // ch:在窗体comboBox列表中显示设备名 | en:Display device name in the form list
            for (int i = 0; i < m_ltDeviceList.Count; i++)
            {
                if (m_ltDeviceList[i].nTLayerType == CSystem.MV_GIGE_DEVICE)  //相机的类型是GEV 
                {
                    CGigECameraInfo gigeInfo = (CGigECameraInfo)m_ltDeviceList[i];

                    if (gigeInfo.UserDefinedName != "")
                    {
                        AddComboxItem("GEV: " + gigeInfo.UserDefinedName + " (" + gigeInfo.chSerialNumber + ")"); //列表增加这个选项
                    }
                    else
                    {
                        AddComboxItem("GEV: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")");
                    }
                }
                else if (m_ltDeviceList[i].nTLayerType == CSystem.MV_USB_DEVICE)  //相机的类型是U3V
                {
                    CUSBCameraInfo usbInfo = (CUSBCameraInfo)m_ltDeviceList[i];

                    if (usbInfo.UserDefinedName != "")
                    {
                        AddComboxItem("U3V: " + usbInfo.UserDefinedName + " (" + usbInfo.chSerialNumber + ")");
                    }
                    else
                    {
                        AddComboxItem("U3V: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")");
                    }
                }
            }
            control_Operation.bnOpen_Enabled_MARK = true;

        }

        private void SetCtrlWhenOpen()  //控件操作在打开的时候
        {
            control_Operation.bnOpen_Enabled_MARK = false;          //按钮--打开设备

            control_Operation.bnClose_Enabled_MARK = true;          //按钮--关闭设备
            control_Operation.bnStartGrab_Enabled_MARK = true;      //按钮--开始采集
            control_Operation.bnStopGrab_Enabled_MARK = false;      //按钮--关闭采集
            control_Operation.bnContinuesMode_Enabled_MARK = true;  //连续模式使能
            control_Operation.bnContinuesMode_Checked_MARK = true;  //连续模式被选中
            control_Operation.bnTriggerMode_Enabled_MARK = true;    //触发模式


            control_Operation.cbSoftTrigger_Enabled_MARK = false;   //软触发模式
            control_Operation.bnTriggerExec_Enabled_MARK = false;   //软触发一次

            control_Operation.tbExposure_Enabled_MARK = true;       //曝光参数
            control_Operation.tbGain_Enabled_MARK = true;           //增益
            control_Operation.tbFrameRate_Enabled_MARK = true;      //频率
            control_Operation.bnGetParam_Enabled_MARK = true;       //获得参数
            control_Operation.bnSetParam_Enabled_MARK = true;       //设置参数  

            control_Operation.tbPixelFormat_Enabled_MARK = false;   //像素格式
        }


        private void SetCtrlWhenClose()  //控件操作在关闭的时候
        {
            control_Operation.bnOpen_Enabled_MARK = true;    //按钮--打开设备

            control_Operation.bnClose_Enabled_MARK = false;
            control_Operation.bnStartGrab_Enabled_MARK = false;
            control_Operation.bnStopGrab_Enabled_MARK = false;
            control_Operation.bnContinuesMode_Enabled_MARK = false;
            control_Operation.bnTriggerMode_Enabled_MARK = false;
            control_Operation.cbSoftTrigger_Enabled_MARK = false;
            control_Operation.bnTriggerExec_Enabled_MARK = false;

            control_Operation.bnSaveBmp_Enabled_MARK = false;

            control_Operation.bnSaveJpg_Enabled_MARK = false;

            control_Operation.bnSaveTiff_Enabled_MARK = false;

            control_Operation.bnSavePng_Enabled_MARK = false;

            /*
            tbExposure.Enabled = false;
            tbGain.Enabled = false;
            tbFrameRate.Enabled = false;
            tbPixelFormat.Enabled = false;
            */

            control_Operation.bnGetParam_Enabled_MARK = false;
            control_Operation.bnGetParam_Enabled_MARK = false;
            control_Operation.bnSetParam_Enabled_MARK = false;
            control_Operation.bnStartRecord_Enabled_MARK = false;
            control_Operation.bnStopRecord_Enabled_MARK = false;
        }


        /// <summary>
        /// 打开设备
        /// </summary>
        public void OpenDevice(int cbDeviceListSelectedIndex)
        {
            if (m_ltDeviceList.Count == 0 || cbDeviceListSelectedIndex == -1)  //如果设备列表为0或者没有在ComboBox中没有选择；
            {
                ShowErrorMsg("No device, please select", 0);
                return;
            }

            // ch:获取选择的设备信息 | en:Get selected device information
            CCameraInfo device = m_ltDeviceList[cbDeviceListSelectedIndex];

            // ch:打开设备 | en:Open device
            if (null == m_MyCamera)
            {
                m_MyCamera = new CCamera();
                if (null == m_MyCamera)
                {
                    return;
                }


                //***********//
                control_Operation.bnContinuesMode_Checked_MARK = true;
            }

            int nRet = m_MyCamera.CreateHandle(ref device);  //创建手柄
            if (CErrorDefine.MV_OK != nRet)   //MV_OK = 0
            {
                return;
            }

            nRet = m_MyCamera.OpenDevice();
            if (CErrorDefine.MV_OK != nRet)  //失败
            {
                m_MyCamera.DestroyHandle();   //销毁手柄
                ShowErrorMsg("Device open fail!", nRet);
                return;
            }

            // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
            if (device.nTLayerType == CSystem.MV_GIGE_DEVICE)
            {
                int nPacketSize = m_MyCamera.GIGE_GetOptimalPacketSize();
                if (nPacketSize > 0)
                {
                    nRet = m_MyCamera.SetIntValue("GevSCPSPacketSize", (uint)nPacketSize);
                    if (nRet != CErrorDefine.MV_OK)
                    {
                        ShowErrorMsg("Set Packet Size failed!", nRet);
                    }
                }
            }
            //控件操作
            SetCtrlWhenOpen();


        }


        public void CloseDevice()
        {
            CloseClick();
            SetCtrlWhenClose();
        }


        /// <summary>
        /// 打开连续模式
        /// </summary>
        public void OpenContinuesMode()
        {


            // ch:打开连续模式 | en:Open Continues Mode   
            control_Operation.bnTriggerMode_Checked_MARK = false;
            control_Operation.bnContinuesMode_Checked_MARK = true;
            control_Operation.bnTriggerMode_Enabled_MARK = true;
            control_Operation.bnContinuesMode_Enabled_MARK = false;


            if (control_Operation.bnContinuesMode_Checked_MARK)
            {
                m_MyCamera.SetEnumValue("TriggerMode", (uint)MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);  //设置触发源为-关闭- }
                control_Operation.cbSoftTrigger_Enabled_MARK = false;//软触发--使能关闭
                control_Operation.bnTriggerExec_Enabled_MARK = false;//软触发一次--使能关闭
            }
        }
        /// <summary>
        /// 打开触发模式
        /// </summary>
        public void TriggerMode()
        {
            // ch:打开触发模式 | en:Open Trigger Mode
            control_Operation.bnContinuesMode_Checked_MARK = false;
            control_Operation.bnTriggerMode_Checked_MARK = true;
            control_Operation.bnContinuesMode_Enabled_MARK = true;
            control_Operation.bnTriggerMode_Enabled_MARK = false;

            // ch:打开触发模式 | en:Open Trigger Mode
            if (control_Operation.bnTriggerMode_Checked_MARK)
            {
                m_MyCamera.SetEnumValue("TriggerMode", (uint)MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);  //开启触发模式

                // ch:触发源选择:0 - Line0; | en:Trigger source select:0 - Line0;
                //           1 - Line1;
                //           2 - Line2;
                //           3 - Line3;
                //           4 - Counter;计数器
                //           7 - Software;软触发
                if (control_Operation.cbSoftTrigger_Checked_MARK) //软触发打开
                {

                    m_MyCamera.SetEnumValue("TriggerSource", (uint)MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);  //设置触发源为-7-software（软触发一次）
                    if (m_bGrabbing)
                    {
                        control_Operation.bnTriggerExec_Enabled_MARK = true;  //触发一次勾选框使能
                    }
                }
                else
                {
                    m_MyCamera.SetEnumValue("TriggerSource", (uint)MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0); //设置触发源为-0- Line0（软触发）
                }
                control_Operation.cbSoftTrigger_Enabled_MARK = true; //软触发使能
            }

        }





        //ch:接收线程进程
        public void ReceiveThreadProcess()
        {
            int nRet = CErrorDefine.MV_OK;

            while (m_bGrabbing)//采集开关开
            {
                CFrameout pcFrameInfo = new CFrameout();  //电脑帧信息
                CDisplayFrameInfo pcDisplayInfo = new CDisplayFrameInfo();    //电脑显示信息
                CDisplayFrameInfo pcDisplayInfo2 = new CDisplayFrameInfo();    //电脑显示信息
                CPixelConvertParam pcConvertParam = new CPixelConvertParam(); //电脑转换参数

                nRet = m_MyCamera.GetImageBuffer(ref pcFrameInfo, 1000);      //获取图像缓冲
                if (CErrorDefine.MV_OK == nRet)
                {
                    if (m_bRecord)//记录开关
                    {
                        CInputFrameInfo pcInputFrameInfo = new CInputFrameInfo();
                        pcInputFrameInfo.InImage = pcFrameInfo.Image;
                        m_MyCamera.InputOneFrame(ref pcInputFrameInfo);
                    }

                    //lock关键字是C#中用于实现线程同步的重要工具，通过它可以确保多个线程在访问共享资源时不会发生竞争条件，从而保证数据的一致性和程序的稳定性。
                    //使用lock时需要注意选择合适的锁对象，避免死锁，并控制锁的粒度以提高性能。
                    lock (BufForDriverLock)
                    {
                        if (null != m_pcImgForDriver)// 如果已有图像信息
                        {
                            m_pcImgForDriver.Destory();
                            m_pcImgForDriver = null;
                        }

                        m_pcImgForDriver = pcFrameInfo.Image.Clone() as CImage;
                        m_pcImgSpecInfo = pcFrameInfo.FrameSpec;
                    }

                    if (m_bRenderByBitmap) //渲染位图
                    {
                        Bitmap pcBitmap = m_MyCamera.ImageToBitmap(ref pcFrameInfo); //位图
                        if (null != pcBitmap)
                        {
                            if (null == m_pcGraphic1)//图形
                            {
                                m_pcGraphic1 = Picture1_CreateGraphics; // pictureBox1.CreateGraphics();
                                m_pcGraphic2 = Picture2_CreateGraphics;// pictureBox2.CreateGraphics();

                            }


                            Rectangle pcDstRect = new Rectangle(0, 0, PictureBox1_W, PictureBox1_H); //获得图像的框架大小
                            Rectangle pcDstRect2 = new Rectangle(0, 0, PictureBox2_W, PictureBox2_W); //获得图像的框架大小

                            Rectangle pcSrcRect = new Rectangle(0, 0, pcBitmap.Width, pcBitmap.Height);
                            Rectangle pcSrcRect2 = new Rectangle(0, 0, pcBitmap.Width, pcBitmap.Height);
                            m_pcGraphic1.DrawImage(pcBitmap, pcDstRect, pcSrcRect, GraphicsUnit.Pixel);  //根据框架的大小绘制图像到PictureBox中
                            m_pcGraphic2.DrawImage(pcBitmap, pcDstRect2, pcSrcRect2, GraphicsUnit.Pixel);  //根据框架的大小绘制图像到PictureBox中
                            pcBitmap.Dispose();//释放此Image的资源
                        }
                    }
                    else
                    {
                        pcDisplayInfo.WindowHandle = Picture1_Handle;//电脑显示信息的窗口句柄 = 控件 PictureBox的句柄
                        pcDisplayInfo2.WindowHandle = Picture2_Handle;//电脑显示信息的窗口句柄 = 控件 PictureBox2的句柄

                        pcDisplayInfo.Image = pcFrameInfo.Image;  //电脑显示信息的图像  = 电脑帧信息的图像
                        pcDisplayInfo2.Image = pcFrameInfo.Image;  //电脑显示信息的图像  = 电脑帧信息的图像
                        m_MyCamera.DisplayOneFrame(ref pcDisplayInfo); //显示一个帧
                        m_MyCamera.DisplayOneFrame(ref pcDisplayInfo2); //显示一个帧
                    }
                    m_MyCamera.FreeImageBuffer(ref pcFrameInfo); //图像缓冲
                }
                else
                {
                    if (control_Operation.bnTriggerMode_Checked_MARK) //点击触发模式暂停5s
                    {
                        Thread.Sleep(5);
                    }
                }
            }
        }


        // ch:像素类型是否为Mono格式 | en:If Pixel Type is Mono 
        private Boolean IsMono(MvGvspPixelType enPixelType)
        {
            switch (enPixelType)
            {
                case MvGvspPixelType.PixelType_Gvsp_Mono1p:
                case MvGvspPixelType.PixelType_Gvsp_Mono2p:
                case MvGvspPixelType.PixelType_Gvsp_Mono4p:
                case MvGvspPixelType.PixelType_Gvsp_Mono8:
                case MvGvspPixelType.PixelType_Gvsp_Mono8_Signed:
                case MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                case MvGvspPixelType.PixelType_Gvsp_Mono14:
                case MvGvspPixelType.PixelType_Gvsp_Mono16:
                    return true;
                default:
                    return false;
            }
        }

        // ch:取图前的必要操作步骤 | en:Necessary operation before grab
        private Int32 NecessaryOperBeforeGrab()
        {
            // ch:取图像宽 | en:Get Iamge Width
            CIntValue pcWidth = new CIntValue();
            int nRet = m_MyCamera.GetIntValue("Width", ref pcWidth);
            if (CErrorDefine.MV_OK != nRet) //报错
            {
                ShowErrorMsg("Get Width Info Fail!", nRet);
                return nRet;
            }
            m_nCurWidth = (UInt32)pcWidth.CurValue; //无符号32位数值


            // ch:取图像高 | en:Get Iamge Height
            CIntValue pcHeight = new CIntValue();
            nRet = m_MyCamera.GetIntValue("Height", ref pcHeight);
            if (CErrorDefine.MV_OK != nRet)
            {
                ShowErrorMsg("Get Height Info Fail!", nRet);
                return nRet;
            }
            m_nCurHeight = (UInt32)pcHeight.CurValue;

            // ch:取像素格式 | en:Get Pixel Format
            CEnumValue pcPixelFormat = new CEnumValue();
            nRet = m_MyCamera.GetEnumValue("PixelFormat", ref pcPixelFormat);
            if (CErrorDefine.MV_OK != nRet)
            {
                ShowErrorMsg("Get Pixel Format Fail!", nRet);
                return nRet;
            }
            m_emPixelType = (MvGvspPixelType)pcPixelFormat.CurValue;

            return CErrorDefine.MV_OK;
        }

        /// <summary>
        /// 已经开始采集，控件操作
        /// </summary>
        public void SetCtrlWhenStartGrab()
        {
            control_Operation.bnStartGrab_Enabled_MARK = false;
            control_Operation.bnStopGrab_Enabled_MARK = true;

            if (control_Operation.bnTriggerMode_Checked_MARK && control_Operation.cbSoftTrigger_Checked_MARK) //选择触发模式和勾选软触发
            {
                control_Operation.bnTriggerExec_Enabled_MARK = true; //软触发使能
            }

            control_Operation.bnSaveBmp_Enabled_MARK = true;    //保存BMP图片
            control_Operation.bnSaveJpg_Enabled_MARK = true;    //保存Jpg图片
            control_Operation.bnSaveTiff_Enabled_MARK = true;   //保存Tiff图片
            control_Operation.bnSavePng_Enabled_MARK = true;     //保存Png图片
            control_Operation.bnStartRecord_Enabled_MARK = true;  //开始录像按钮使能
            control_Operation.bnStopRecord_Enabled_MARK = false;  //停止录像按钮取消使能
        }

        /// <summary>
        /// 开始采集
        /// </summary>
        public void StartGrab()
        {
            // ch:前置配置 | en:pre-operation
            int nRet = NecessaryOperBeforeGrab();// 取图前的必要操作步骤
            if (CErrorDefine.MV_OK != nRet)
            {
                return;
            }

            // ch:标志位置位true | en:Set position bit true  
            m_bGrabbing = true; //采集开

            //m_bRenderByBitmap = true;
            m_hReceiveThread = new Thread(ReceiveThreadProcess); //接收线程进程开始
            m_hReceiveThread.Start(); //接受开始             

            // ch:开始采集 | en:Start Grabbing
            nRet = m_MyCamera.StartGrabbing();
            if (CErrorDefine.MV_OK != nRet)
            {
                m_bGrabbing = false;
                m_hReceiveThread.Join();  //终止线程
                ShowErrorMsg("Start Grabbing Fail!", nRet);

                return;
            }

            // ch:控件操作 | en:Control Operation
            // ch:控件操作 | en:Control Operation
            SetCtrlWhenStartGrab(); //已经开始采集，控件操作
        }

        /// <summary>
        /// 软触发勾选框的点击事件
        /// </summary>
        public void _cbSoftTrigger_CheckedChanged_incident()
        {
            control_Operation.cbSoftTrigger_Checked_MARK = true;
            if (control_Operation.cbSoftTrigger_Checked_MARK)
            {
                control_Operation.bnTriggerExec_Enabled_MARK = true;
                // ch:触发源设为软触发 | en:Set trigger source as Software
                m_MyCamera.SetEnumValue("TriggerSource", (uint)MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
                if (m_bGrabbing)// 采集开关 = true 的时候
                {
                    control_Operation.bnTriggerExec_Enabled_MARK = true;//可以点击 “软触发一次” 控件
                }
            }
            else //取消勾选软触发时
            {
                control_Operation.cbSoftTrigger_Checked_MARK = false;
                control_Operation.bnTriggerExec_Enabled_MARK = false;
                //ch:触发源设为Line0
                m_MyCamera.SetEnumValue("TriggerSource", (uint)MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
                control_Operation.bnTriggerExec_Enabled_MARK = false;  //点击 “软触发一次” 控件 无效
            }
        }

        //ch:点击软触发一次 事件
        public void TriggerExec()
        {
            // ch:触发命令 | en:Trigger command
            int nRet = m_MyCamera.SetCommandValue("TriggerSoftware");//设置命令值--（触发软件）
            if (CErrorDefine.MV_OK != nRet)
            {
                ShowErrorMsg("Trigger Software Fail!", nRet);
            }
        }


        /// <summary>
        /// 采集关闭的时候-控件操作
        /// </summary>
        private void SetCtrlWhenStopGrab()
        {
            control_Operation.bnStartGrab_Enabled_MARK = true;    //开始采集按钮
            control_Operation.bnStopGrab_Enabled_MARK = false;
            control_Operation.bnTriggerExec_Enabled_MARK = false;

            control_Operation.bnSaveBmp_Enabled_MARK = false;
            control_Operation.bnSaveJpg_Enabled_MARK = false;
            control_Operation.bnSaveTiff_Enabled_MARK = false;
            control_Operation.bnSavePng_Enabled_MARK = false;

            control_Operation.bnStartRecord_Enabled_MARK = false;
            control_Operation.bnStopRecord_Enabled_MARK = false;


        }

        /// <summary>
        /// 停止采集事件
        /// </summary>
        public void StopGrab()
        {
            // ch:标志位设为false | en:Set flag bit false
            m_bGrabbing = false;     //采集开关
            m_hReceiveThread.Join(); //接受线程终止

            // ch:停止采集 | en:Stop Grabbing
            int nRet = m_MyCamera.StopGrabbing();  //相机停止采集
            if (nRet != CErrorDefine.MV_OK)
            {
                ShowErrorMsg("Stop Grabbing Fail!", nRet);
            }

            // ch:采集关闭的时候-控件操作 | en:Control Operation
            //--------------控件操作-----------//
            SetCtrlWhenStopGrab();
        }

        /// <summary>
        /// 点击保存Bmp格式图片
        /// </summary>
        public void SaveBmp()
        {
            if (false == m_bGrabbing)
            {
                ShowErrorMsg("Not Start Grabbing", 0);
                return;
            }

            CSaveImgToFileParam stSaveFileParam = new CSaveImgToFileParam(); //保存文件参数

            lock (BufForDriverLock)//:用于从驱动获取图像的缓存
            {
                //ch:当图像信息为空 或者 帧长度为0 时报错
                if (null == m_pcImgForDriver || 0 == m_pcImgForDriver.FrameLen)
                {
                    ShowErrorMsg("Save Bmp Fail!", 0);
                    return;
                }

                //ch:保存到文件
                stSaveFileParam.ImageType = MV_SAVE_IAMGE_TYPE.MV_IMAGE_BMP;//图像类型
                stSaveFileParam.Image = m_pcImgForDriver;  //图像信息
                stSaveFileParam.MethodValue = 2;  //方法值

                //ch:图像路径
                stSaveFileParam.ImagePath = "Image_w" + stSaveFileParam.Image.Width.ToString() + "_h" + stSaveFileParam.Image.Height.ToString() + "_fn" + m_pcImgSpecInfo.FrameNum.ToString() + ".bmp";
                int nRet = m_MyCamera.SaveImageToFile(ref stSaveFileParam); //保存图像到文件的方法
                if (CErrorDefine.MV_OK != nRet)
                {
                    ShowErrorMsg("Save Bmp Fail!", nRet);
                    return;
                }

                // 保存图像到缓存--保存到缓存的参数信息
                m_pcSaveParam.InImage = m_pcImgForDriver;  //图像
                m_pcSaveParam.ImageType = MV_SAVE_IAMGE_TYPE.MV_IMAGE_BMP;  //图像类型
                m_pcSaveParam.MethodValue = 2;  //方法值

                nRet = m_MyCamera.SaveImageEx(ref m_pcSaveParam);//保存到缓存的参数信息
                if (nRet != CErrorDefine.MV_OK)
                {
                    DebugInfo("SaveImageEx Failed" + nRet.ToString());
                }

                //ch:保存成功后
                else
                {
                    //ch:字符保存信息
                    String strSaveInfo = String.Format("SaveImageEx Success: Height[{0}], Width[{1}], FrameLen[{2}], ImageType[{3}]",
                    m_pcSaveParam.OutImage.Height, m_pcSaveParam.OutImage.Width, m_pcSaveParam.OutImage.FrameLen, m_pcSaveParam.ImageType);
                    DebugInfo(strSaveInfo);
                }
            }

            ShowErrorMsg("Save Succeed!", 0);
        }

        /// <summary>
        /// 点击保存Jpg格式图片
        /// </summary>
        public void SaveJpg()
        {
            if (false == m_bGrabbing)
            {
                ShowErrorMsg("Not Start Grabbing", 0);
                return;
            }

            CSaveImgToFileParam stSaveFileParam = new CSaveImgToFileParam();

            lock (BufForDriverLock)
            {
                if (null == m_pcImgForDriver || 0 == m_pcImgForDriver.FrameLen)
                {
                    ShowErrorMsg("Save Jpeg Fail!", 0);
                    return;
                }
                stSaveFileParam.ImageType = MV_SAVE_IAMGE_TYPE.MV_IMAGE_JPEG;
                stSaveFileParam.Image = m_pcImgForDriver;
                stSaveFileParam.Quality = 80;
                stSaveFileParam.MethodValue = 2;
                stSaveFileParam.ImagePath = "Image_w" + stSaveFileParam.Image.Width.ToString() + "_h" + stSaveFileParam.Image.Height.ToString() + "_fn" + m_pcImgSpecInfo.FrameNum.ToString() + ".jpg";
                int nRet = m_MyCamera.SaveImageToFile(ref stSaveFileParam);
                if (CErrorDefine.MV_OK != nRet)
                {
                    ShowErrorMsg("Save Jpeg Fail!", nRet);
                    return;
                }
            }

            ShowErrorMsg("Save Succeed!", 0);
        }

        /// <summary>
        /// 点击保存Png格式图片
        /// </summary>
        public void SavePng()
        {
            if (false == m_bGrabbing)
            {
                ShowErrorMsg("Not Start Grabbing", 0);
                return;
            }

            CSaveImgToFileParam stSaveFileParam = new CSaveImgToFileParam();

            lock (BufForDriverLock)
            {
                if (null == m_pcImgForDriver || 0 == m_pcImgForDriver.FrameLen)
                {
                    ShowErrorMsg("Save Png Fail!", 0);
                    return;
                }
                stSaveFileParam.ImageType = MV_SAVE_IAMGE_TYPE.MV_IMAGE_PNG;
                stSaveFileParam.Image = m_pcImgForDriver;
                stSaveFileParam.Quality = 9;
                stSaveFileParam.MethodValue = 2;
                stSaveFileParam.ImagePath = "Image_w" + stSaveFileParam.Image.Width.ToString() + "_h" + stSaveFileParam.Image.Height.ToString() + "_fn" + m_pcImgSpecInfo.FrameNum.ToString() + ".png";
                int nRet = m_MyCamera.SaveImageToFile(ref stSaveFileParam);
                if (CErrorDefine.MV_OK != nRet)
                {
                    ShowErrorMsg("Save Png Fail!", nRet);
                    return;
                }
            }

            ShowErrorMsg("Save Succeed!", 0);
        }

        /// <summary>
        /// 点击保存Tiff格式图片
        /// </summary>
        public void SaveTiff()
        {
            if (false == m_bGrabbing)
            {
                ShowErrorMsg("Not Start Grabbing", 0);
                return;
            }

            CSaveImgToFileParam stSaveFileParam = new CSaveImgToFileParam();

            lock (BufForDriverLock)
            {
                if (null == m_pcImgForDriver || 0 == m_pcImgForDriver.FrameLen)
                {
                    ShowErrorMsg("Save Tiff Fail!", 0);
                    return;
                }
                stSaveFileParam.ImageType = MV_SAVE_IAMGE_TYPE.MV_IMAGE_TIF;
                stSaveFileParam.Image = m_pcImgForDriver;
                stSaveFileParam.MethodValue = 2;
                stSaveFileParam.ImagePath = "Image_w" + stSaveFileParam.Image.Width.ToString() + "_h" + stSaveFileParam.Image.Height.ToString() + "_fn" + m_pcImgSpecInfo.FrameNum.ToString() + ".tif";
                int nRet = m_MyCamera.SaveImageToFile(ref stSaveFileParam);
                if (CErrorDefine.MV_OK != nRet)
                {
                    ShowErrorMsg("Save Tiff Fail!", nRet);
                    return;
                }
            }

            ShowErrorMsg("Save Succeed!", 0);
        }

        /// <summary>
        /// ch:获取触发模式 | en:Get Trigger Mode
        /// </summary>
        public void GetTriggerMode()
        {

            CEnumValue pcEnumValue = new CEnumValue();  //电脑枚举值
            int nRet = m_MyCamera.GetEnumValue("TriggerMode", ref pcEnumValue);
            if (CErrorDefine.MV_OK == nRet)
            {
                // 触发模式ON情况下
                if ((uint)MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON == pcEnumValue.CurValue)
                {
                    control_Operation.bnTriggerMode_Checked_MARK = true;     //自动点击选择触发模式
                    control_Operation.bnContinuesMode_Checked_MARK = false;  //关闭连续模式

                    // 获取触发源
                    nRet = m_MyCamera.GetEnumValue("TriggerSource", ref pcEnumValue);
                    if (CErrorDefine.MV_OK == nRet)
                    {
                        if ((uint)MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE == pcEnumValue.CurValue) //触发源为line7--软触发
                        {
                            control_Operation.cbSoftTrigger_Checked_MARK = true; //软触发勾选框自动选择
                            if (m_bGrabbing) //采集开始的情况下
                            {
                                control_Operation.bnTriggerExec_Enabled_MARK = true; //自动启动软触发一次
                            }
                            control_Operation.cbSoftTrigger_Enabled_MARK = true; //软触发勾选框勾选
                        }
                    }
                }
                else
                {
                    // 连续模式下
                    control_Operation.bnContinuesMode_Checked_MARK = true; //自动选择点击连续模式
                    control_Operation.bnTriggerMode_Checked_MARK = false;   //关闭触发模式
                }
            }
        }


        /// <summary>
        /// 获取参数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void GetParam()
        {
            CFloatValue pcFloatValue = new CFloatValue(); //电脑浮点值
            CEnumValue pcEnumValue = new CEnumValue();    //电脑枚举值
            CEnumEntry pcEntryValue = new CEnumEntry();   //电脑输入值
            int nRet = CErrorDefine.MV_OK;

            // 获取触发模式
            GetTriggerMode();

            // 获取曝光时间
            nRet = m_MyCamera.GetFloatValue("ExposureTime", ref pcFloatValue);
            if (CErrorDefine.MV_OK == nRet) //正确时
            {
                //CurValue 是一个浮点数值（通常是 float 或 double 类型），表示当前值。
                //ToString("F1") 方法将浮点数值转换为字符串，并格式化为小数点后一位。
                tbExposure_Text = pcFloatValue.CurValue.ToString("F1");
            }

            // 获取增益
            nRet = m_MyCamera.GetFloatValue("Gain", ref pcFloatValue);
            if (CErrorDefine.MV_OK == nRet)
            {
                tbGain_Text = pcFloatValue.CurValue.ToString("F1");
            }

            // 获取帧率
            nRet = m_MyCamera.GetFloatValue("ResultingFrameRate", ref pcFloatValue);
            if (CErrorDefine.MV_OK == nRet)
            {
                tbFrameRate_Text = pcFloatValue.CurValue.ToString("F1");
            }

            // 获取像素格式
            nRet = m_MyCamera.GetEnumValue("PixelFormat", ref pcEnumValue);
            if (CErrorDefine.MV_OK == nRet)
            {
                pcEntryValue.Value = pcEnumValue.CurValue;
                nRet = m_MyCamera.GetEnumEntrySymbolic("PixelFormat", ref pcEntryValue);
                if (CErrorDefine.MV_OK == nRet)
                {
                    tbPixelFormat_Text = pcEntryValue.Symbolic;
                }
            }
        }


        //ch:点击设置参数按钮
        public void SetParam()
        {
            try
            {
                float.Parse(tbExposure_Text); //曝光
                float.Parse(tbGain_Text); //增益
                float.Parse(tbFrameRate_Text); //帧率
            }
            catch
            {
                ShowErrorMsg("Please enter correct type!", 0);
                return;
            }
            //ch:曝光
            m_MyCamera.SetEnumValue("ExposureAuto", 0); //关闭自动曝光
            int nRet = m_MyCamera.SetFloatValue("ExposureTime", float.Parse(tbExposure_Text)); //设置曝光时间
            if (nRet != CErrorDefine.MV_OK)
            {
                ShowErrorMsg("Set Exposure Time Fail!", nRet);
            }

            //ch:增益值
            m_MyCamera.SetEnumValue("GainAuto", 0); //关闭自动增益
            nRet = m_MyCamera.SetFloatValue("Gain", float.Parse(tbGain_Text)); //设置增益值
            if (nRet != CErrorDefine.MV_OK)
            {
                ShowErrorMsg("Set Gain Fail!", nRet);
            }

            //ch:帧率
            nRet = m_MyCamera.SetFloatValue("AcquisitionFrameRate", float.Parse(tbFrameRate_Text));//设置采集帧率
            if (nRet != CErrorDefine.MV_OK)
            {
                ShowErrorMsg("Set Frame Rate Fail!", nRet);
            }
        }

        /// <summary>
        /// 界面关闭，释放资源
        /// </summary>
        public void CloseClick()
        {
            // ch:取流标志位清零 | en:Reset flow flag bit
            if (m_bGrabbing == true)
            {
                StopGrab(); //标志位清零，停止采集，部分控件关闭使能
            }

            // ch:关闭设备 | en:Close Device
            m_MyCamera.CloseDevice();  //关闭设备
            m_MyCamera.DestroyHandle();  //销毁控制线程

            // ch:控件操作 | en:Control Operation
            //  SetCtrlWhenClose();
        }

        /// <summary>
        /// 开始录像
        /// </summary>
        /// <param name="tbText"></param>
        public void StartRecord()
        {


            if (false == m_bGrabbing) //当采集没开始时，开启失败
            {
                ShowErrorMsg("采集没有启动", 0);
                return;
            }

            CRecordParam pcRecordParam = new CRecordParam(); //电脑录像参数

            pcRecordParam.enPixelType = m_emPixelType;//像素类型
            pcRecordParam.Height = m_nCurHeight;      //图像高度
            pcRecordParam.Width = m_nCurWidth;        //图像宽度
            pcRecordParam.FrameRate = float.Parse(tbFrameRate_Text);//帧率

            //es:单位时间内通过信道传输的信息量称为比特传输速率，单位是比特/秒（bit/s），简称比特率（bitrate）
            //比特率越高，传送的数据越大。视频中的比特率（码率）是指由模拟信号转换为数字信号的采样率,常利用比特率衡量视频文件质量;
            pcRecordParam.BitRate = 1000;             //比特率 

            pcRecordParam.FilePath = "./Record.avi";  //文件路径
            pcRecordParam.RecordFmtType = MV_RECORD_FORMAT_TYPE.MV_FORMAT_TYPE_AVI;

            Int32 nRet = m_MyCamera.StartRecord(ref pcRecordParam); //记录类型
            if (nRet != CErrorDefine.MV_OK)
            {
                ShowErrorMsg("Start Record Fail!", nRet);
            }

            //参数准备完毕--打开记录开关
            m_bRecord = true;

            SetCtrlWhenStartRecord();//开始录像时，控件设置
        }

        /// <summary>
        /// 停止录像
        /// </summary>
        public void StopRecord()
        {

            if (false == m_bGrabbing) //当采集没开始时，关闭失败
            {
                ShowErrorMsg("采集没有启动", 0);
                return;
            }

            Int32 nRet = m_MyCamera.StopRecord();
            if (nRet != CErrorDefine.MV_OK)
            {
                ShowErrorMsg("Stop Record Fail!", nRet);
            }

            //关闭--记录开关
            m_bRecord = false;
            SetCtrlWhenStopRecord();
        }

        private void SetCtrlWhenStartRecord() //开始录像时，控件设置
        {
            control_Operation.bnStartRecord_Enabled_MARK = false; //开始录像失效
            control_Operation.bnStopRecord_Enabled_MARK = true; //停止录像使能
        }

        private void SetCtrlWhenStopRecord() //停止录像时，控件设置
        {
            control_Operation.bnStartRecord_Enabled_MARK = true; //开始录像使能
            control_Operation.bnStopRecord_Enabled_MARK = false; //停止录像失效
        }









    }
}
